package com.ihcy.base.service.impl;

import com.ihcy.base.config.ExecuteBatchUser;
import com.ihcy.base.core.ExceptionEnum;
import com.ihcy.base.core.ServerException;
import com.ihcy.base.enums.PositioneEnum;
import com.ihcy.base.model.entity.User;
import com.ihcy.base.model.vo.request.RegisterUserRequest;
import com.ihcy.base.model.vo.request.UserQueryRequest;
import com.ihcy.base.repository.UserRepository;
import com.ihcy.base.service.IUserService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.Predicate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Service
public class UserServiceImpl implements IUserService {


    private final UserRepository userRepository;
    private final ExecuteBatchUser executeBatchUser;

    public UserServiceImpl(UserRepository userRepository, ExecuteBatchUser executeBatchUser) {
        this.userRepository = userRepository;
        this.executeBatchUser = executeBatchUser;
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public User registerUser(User user) {
        return userRepository.save(user);
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public Boolean deleteUser(Long id) {
        User user = userRepository.getById(id);
        user.setIsDeleted(Boolean.TRUE);
        userRepository.save(user);
        return Boolean.TRUE;
    }


    @Override
    public void addBatchUser(List<RegisterUserRequest> list) {
        executeBatchUser.addBatch(User.build(list));
    }

    @Override
    public List<User> findAll() {
        return userRepository.findAll();
    }

    /**
     * public List<User> getList(User user) {
     * Specification<User> specification = (root, query, criteriaBuilder) -> {
     * // 获取比较的属性
     * Path<String> userName = root.get("userName");
     * Path<String> employeeNo = root.get("employeeNo");
     * // 构造查询条件
     * Predicate userNamePredicate = criteriaBuilder.equal(userName, "name");
     * Predicate employeeNoPredicate = criteriaBuilder.equal(employeeNo, "10001");
     * return criteriaBuilder.and(userNamePredicate, employeeNoPredicate);
     * };
     * return userRepository.findAll(specification);
     * }
     */
    @Override
    public Page<User> getPage(UserQueryRequest request, Pageable pageable) {
        Specification<User> specification = (root, criteriaQuery, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            // 单字段查询
            if (StringUtils.isNotBlank(request.getUserName())) {
                Predicate userName = criteriaBuilder.like(root.get("userName"), "%" + request.getUserName() + "%");
                predicates.add(criteriaBuilder.and(userName));
            }
            // 范围查询
            if (request.getCreatedTimeStart() != null) {
                predicates.add(
                        criteriaBuilder.greaterThanOrEqualTo(root.get("createdTime").as(LocalDateTime.class), request.getCreatedTimeStart()));
            }
            if (request.getCreatedTimeEnd() != null) {
                predicates.add(
                        criteriaBuilder.lessThanOrEqualTo(root.get("createdTime").as(LocalDateTime.class), request.getCreatedTimeEnd()));
            }
            // 用作类型强转
            return criteriaQuery.where(predicates.toArray(new Predicate[0])).getRestriction();
        };
        return userRepository.findAll(specification, pageable);
    }

    @Override
    public List<User> getUserByPosition(PositioneEnum position) {
        User user = new User();
        user.setPosition(position);
        Example<User> example = Example.of(user);
        return userRepository.findAll(example);
    }


    /**
     * 负责查询
     * example 不支持组合查询。
     * 只支持字符串的 starts,contains,ends,regex匹配。对于非字符串的属性，只支持精确匹配。
     * 并不支持大于，小于，between等匹配。
     **/
//    @Override
//    public Page<User> getPage(User user, Pageable pageable) {
////        user.setUserName("test"); 示例
//        ExampleMatcher matcher = ExampleMatcher.matching()
//                // 模糊查询匹配开头,即{userName}%
//                .withMatcher("userName", ExampleMatcher.GenericPropertyMatchers.startsWith())
//                // 全部模糊匹配,即%{address}%
//                .withMatcher("address", ExampleMatcher.GenericPropertyMatchers.contains())
//                // 忽略字段
//                .withMatcher("id", ExampleMatcher.GenericPropertyMatchers.ignoreCase());
//        Example<User> example = Example.of(user, matcher);
//        return userRepository.findAll(example, pageable);
//
//    }
    @Override
    public void testException() {
//        int i = 1 / 0;
        throw new ServerException(ExceptionEnum.SIGNATURE_NOT_MATCH);
    }

}
